using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace DigitalTrainSuite.Canvas
{
    class DrawTracks
    {
        private Graphics gobject;
        private double scale;

        /// <summary>
        /// constructor function
        /// </summary>
        /// <param name="g"> the graphics object that will be drawn on</param>
        /// <param name="data">the data set holding all of the layout information</param>
        /// <param name="scale">the scale factor for the track</param>
        public DrawTracks(Graphics g, double scale)
        {
            this.gobject = g;
            this.scale = scale;
        }

		public void drawTrack(DataSetLayout.TrackRow track, DoublePoint offset)
		{
			double x = track.locationX + offset.X;
			double y = track.locationY + offset.Y;

			switch ((TrackType)track.type)
			{
				case TrackType.CurveRightR1:
				case TrackType.CurveRightR2:
				case TrackType.CurveRightR3:
				case TrackType.CurveRightR2_243:
					this.drawRightCurve(x, y, track.radius, track.angle, track.rotation);
					break;
				case TrackType.CurveLeftR1:
				case TrackType.CurveLeftR2:
				case TrackType.CurveLeftR3:
				case TrackType.CurveLeftR2_243:
					this.drawLeftCurve(x, y, track.radius, track.angle, track.rotation);
                    break;
                case TrackType.Straight:
				case TrackType.Straight188:
				case TrackType.Straight172:
				case TrackType.Straight94:
				case TrackType.Straight775:
					this.drawStraight(x, y, track.rotation, track.length);
                    break;
                case TrackType.TurnoutCurveRight:
					this.drawDoubleCurveRight(x, y, track.rotation);
                    break;
                case TrackType.TurnoutCurveLeft:
					this.drawDoubleCurveLeft(x, y, track.rotation);
                    break;
                case TrackType.TurnoutStraightRight:
					this.drawStraightCurveRight(x, y, track.rotation);
                    break;
                case TrackType.TurnoutStraightLeft:
					this.drawStraightCurveLeft(x, y, track.rotation);
                    break;
                case TrackType.DoubleSlipSwitch:
					this.drawCrossTrack(x, y, track.rotation);
                    break;
				default:
					break;
			}
		}

        /// <summary>
        /// Draw function to draw Right Curves
        /// </summary>
        /// <param name="xloc">x location of Curve</param>
        /// <param name="yloc">y location of Curve</param>
        /// <param name="radius">Radius of the arch</param>
        /// <param name="rotation">The amount of rotation for the part</param>
        /// <param name="sweepangle">The sweep angle of the curve</param>
		public void drawRightCurve(double xloc, double yloc, double radius, double sweepangle, double rotation)
        {
            xloc = xloc / scale;
            yloc = yloc / scale;

            double xbox = xloc;
			double ybox = (yloc - (((radius * 2.0) / scale) / 2.0));
            Rectangle rectangle1 = new Rectangle((int)xbox, (int)ybox, (int)((radius*2.0)/scale), (int)((radius*2.0)/scale));
            SolidBrush brush1 = new SolidBrush(Color.Black);
            Pen pen1 = new Pen(brush1, 5);
            Pen pen2 = new Pen(brush1, 1);

			this.gobject.TranslateTransform((float)xloc, (float)yloc);
			this.gobject.RotateTransform((float)rotation);
			this.gobject.TranslateTransform((float)(-(xloc)), (float)(-yloc));
            //this.gobject.DrawRectangle(pen2, rectangle1); //<!Draw the rectangle that contains the curve
            this.gobject.DrawArc(pen1, rectangle1, 180, (float)sweepangle);  

            //Rotate the object to its original position
            this.gobject.TranslateTransform((float)xloc, (float)yloc);
            this.gobject.RotateTransform((float)-rotation);
            this.gobject.TranslateTransform((float)-(xloc), (float)-yloc);
        }

        /// <summary>
        /// Draw function to draw Left Curves
        /// </summary>
        /// <param name="xloc">x location of Curve</param>
        /// <param name="yloc">y location of Curve</param>
        /// <param name="radius">Radius of the arch</param>
        /// <param name="rotation">The amount of rotation for the part</param>
        /// <param name="sweepangle">The sweep angle of the curve</param>
		public void drawLeftCurve(double xloc, double yloc, double radius, double sweepangle, double rotation)
        {
            xloc = xloc / scale;
            yloc = yloc / scale;

            float xbox = (float)(xloc -((radius*2)/scale));
            float ybox = (float)(yloc - (((radius) / scale)));
            
            Rectangle rectangle1 = new Rectangle((int)xbox, (int)ybox, (int)((radius * 2) / scale), (int)((radius * 2) / scale));
            SolidBrush brush1 = new SolidBrush(Color.Black);
            Pen pen1 = new Pen(brush1, 5);
            Pen pen2 = new Pen(brush1, 1);

            //graphicsObject.DrawRectangle(pen1, rectangle1); //<!Draw the rectangle that contains the curve
            this.gobject.TranslateTransform((float)xloc, (float)yloc);
            this.gobject.RotateTransform((float)rotation);
            this.gobject.TranslateTransform((float)-(xloc), (float)-yloc);
            //this.gobject.DrawRectangle(pen2, rectangle1);
            this.gobject.DrawArc(pen1, rectangle1, 0, (float)-sweepangle);  

            //Rotate object to its original position
            this.gobject.TranslateTransform((float)xloc, (float)yloc);
            this.gobject.RotateTransform((float)-rotation);
            this.gobject.TranslateTransform((float)-(xloc), (float)-yloc);
        }

       /// <summary>
       /// Draw Function to draw a straight track
       /// </summary>
       /// <param name="xstart">X starting location of track</param>
       /// <param name="ystart">Y starting location of track</param>
       /// <param name="rotation">Rotation angle of track</param>
       /// <param name="length">Lenght in mm of track</param>
       /// <param name="scale">Scale factor for the track</param>
		public void drawStraight(double xstart, double ystart, double rotation, double length)
        {
            xstart = xstart / scale;
            ystart = ystart / scale;

            SolidBrush brush1 = new SolidBrush(Color.Black);
            Pen pen1 = new Pen(brush1, 5);

            //Apply rotation angle to the figure and draw the figure
            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);
            this.gobject.DrawLine(pen1, (float)xstart, (float)ystart, (float)xstart, (float)(ystart - (length / scale)));

            //Rotate back to original location
            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)-rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);
        }

        /// <summary>
        /// Function to draw the straight right curve switch track part
        /// </summary>
        /// <param name="xstart">the x location of the part</param>
        /// <param name="ystart">the y location of the part</param>
        /// <param name="rotation">the rotation angle of the part</param>
		public void drawStraightCurveRight(double xstart, double ystart, double rotation)
        {
            xstart = xstart / scale;
            ystart = ystart / scale;

           double xbox = xstart;
           double ybox = (float)(ystart - ((875 / scale)/2));
            
            Rectangle rectangle1 = new Rectangle((int)xbox, (int)ybox, (int)(875 / scale), (int)(875 / scale));
            SolidBrush brush1 = new SolidBrush(Color.Black);
            Pen pen1 = new Pen(brush1, 5);
            Pen pen2 = new Pen(brush1, 1);
            GraphicsPath turnswitch = new GraphicsPath();
            GraphicsPath turnArc = new GraphicsPath();

            turnswitch.AddLine((float)xstart, (float)ystart, (float)xstart, (float)(ystart - (188 / scale)));
            turnArc.AddArc(rectangle1, 180, (float)24.3);

            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);

            //this.gobject.DrawRectangle(pen2, rectangle1); //<!Draw the rectangle the contains the curve
            this.gobject.DrawPath(pen1, turnswitch);
            this.gobject.DrawPath(pen1, turnArc);

            //Rotate object back to its original position
            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)-rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);
        }

        /// <summary>
        /// Function to draw the straight left curve switch track part
        /// </summary>
        /// <param name="xstart">x location of the part</param>
        /// <param name="ystart">y location of the part</param>
        /// <param name="rotation">roation angle of the part</param>
		public void drawStraightCurveLeft(double xstart, double ystart, double rotation)
        {
            xstart = xstart / scale;
            ystart = ystart / scale;

            float xbox =(float)(xstart-((875/scale)));
            float ybox = (float)(ystart - ((875 / scale) / 2));
            
            Rectangle rectangle1 = new Rectangle((int)xbox, (int)ybox, (int)(875 / scale), (int)(875 / scale));
            SolidBrush brush1 = new SolidBrush(Color.Black);
            Pen pen1 = new Pen(brush1, 5);
            Pen pen2 = new Pen(brush1, 1);
            GraphicsPath turnswitch = new GraphicsPath();
            GraphicsPath turnArc = new GraphicsPath();

            turnswitch.AddLine((float)xstart, (float)ystart, (float)xstart, (float)(ystart - (188 / scale)));
            turnArc.AddArc(rectangle1, 0, (float)-24.3);

            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);

            //this.gobject.DrawRectangle(pen2, rectangle1); //<!Draw the rectangle that contains the curve
            this.gobject.DrawPath(pen1, turnswitch);
            this.gobject.DrawPath(pen1, turnArc);

            //Rotate object back to its original position
            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)-rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);
        }

        /// <summary>
        /// Function to draw the double right curve switch track part
        /// </summary>
        /// <param name="xstart">the x location of the part</param>
        /// <param name="ystart">the y location of the part</param>
        /// <param name="rotation">the angle of rotation of the part</param>
		public void drawDoubleCurveRight(double xstart, double ystart, double rotation)
        {
            xstart = xstart / scale;
            ystart = ystart / scale;

            double xbox1 = xstart;
            double ybox1 = (ystart - ((360 / scale)));
            double xbox2 = xstart;
            double ybox2 = (ybox1 - (77 / scale));

            Rectangle rectangle1 = new Rectangle((int)xbox1, (int)ybox1, (int)(720 / scale), (int)(720 / scale));
            Rectangle rectangle2 = new Rectangle((int)xbox2, (int)ybox2, (int)(720 / scale), (int)(720 / scale));
            SolidBrush brush1 = new SolidBrush(Color.Black);
            Pen pen1 = new Pen(brush1, 5);
            Pen pen2 = new Pen(brush1, 1);
            GraphicsPath turnswitch = new GraphicsPath();
            GraphicsPath turnArc1 = new GraphicsPath();
            GraphicsPath turnArc2 = new GraphicsPath();

            turnswitch.AddLine((float)xstart, (float)ystart, (float)xstart, (float)(ystart - (77 / scale)));
            turnArc1.AddArc(rectangle1, 180, 30);
            turnArc2.AddArc(rectangle2, 180, 30);

            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);

            //graphicsObject.DrawRectangle(pen2, rectangle1); //<!Draw the rectangle that contains the 1st curve
            //graphicsObject.DrawRectangle(pen2, rectangle2); //<1Draw the rectangle the contains the 2nd curve
            this.gobject.DrawPath(pen1, turnswitch);
            this.gobject.DrawPath(pen1, turnArc1);
            this.gobject.DrawPath(pen1, turnArc2);

            //Rotate object back to its original position
            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)-rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);
        }

        /// <summary>
        /// Function to draw the double left curve switch track part
        /// </summary>
        /// <param name="xstart">x location of the part</param>
        /// <param name="ystart">y location of the part</param>
        /// <param name="rotation">rotation angle of the part</param>
		public void drawDoubleCurveLeft(double xstart, double ystart, double rotation)
        {
            xstart = xstart / scale;
            ystart = ystart / scale;

            float xbox1 = (float)(xstart-(720/scale));
            float ybox1 = (float)(ystart - ((360 / scale)));
            float xbox2 = (float)(xstart - (720 / scale)); 
            float ybox2 = (float)(ybox1 - (77 / scale));

            Rectangle rectangle1 = new Rectangle((int)xbox1, (int)ybox1, (int)(720 / scale), (int)(720 / scale));
            Rectangle rectangle2 = new Rectangle((int)xbox2, (int)ybox2, (int)(720 / scale), (int)(720 / scale));
            SolidBrush brush1 = new SolidBrush(Color.Black);
            Pen pen1 = new Pen(brush1, 5);
            Pen pen2 = new Pen(brush1, 1);
            GraphicsPath turnswitch = new GraphicsPath();
            GraphicsPath turnArc1 = new GraphicsPath();
            GraphicsPath turnArc2 = new GraphicsPath();

            turnswitch.AddLine((float)xstart, (float)ystart, (float)xstart, (float)(ystart - (77 / scale)));
            turnArc1.AddArc(rectangle1, 0, -30);
            turnArc2.AddArc(rectangle2, 0, -30);

            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);

            //this.gobject.DrawRectangle(pen2, rectangle1); //<!Draw rectangle that contains the 1st curve
            //this.gobject.DrawRectangle(pen2, rectangle2); //<!Draw the rectangle that contains the 2nd curve
            this.gobject.DrawPath(pen1, turnswitch);
            this.gobject.DrawPath(pen1, turnArc1);
            this.gobject.DrawPath(pen1, turnArc2);

            //Rotate object back to its original position
            this.gobject.TranslateTransform((float)xstart, (float)ystart);
            this.gobject.RotateTransform((float)-rotation);
            this.gobject.TranslateTransform((float)-(xstart), (float)-ystart);
        }

        /// <summary>
        /// Function to draw the cross switch track part
        /// </summary>
        /// <param name="xstart">x location of the part</param>
        /// <param name="ystart">y locatoin of the part</param>
        /// <param name="rotation">rotation angle of the part</param>
		public void drawCrossTrack(double xstart, double ystart, double rotation)
        {
            double xstartscaled = xstart / scale;
            double ystartscaled = ystart / scale;
           
            SolidBrush brush1 = new SolidBrush(Color.Black);
            GraphicsPath crossswitch = new GraphicsPath();
            Pen pen1 = new Pen(brush1, 5);

            GraphicsPath straight = new GraphicsPath();
            GraphicsPath branch = new GraphicsPath();

            straight.AddLine((float)xstartscaled, (float)ystartscaled, (float)xstartscaled, (float)(ystartscaled - (188 / scale)));
            branch.AddLine((float)xstartscaled, (float)(ystartscaled - ((188 / scale) / 2)), (float)xstartscaled, (float)(ystartscaled - (188 / scale)));

            //Rotate entire piece the desired rotation
            this.gobject.TranslateTransform((float)xstartscaled, (float)ystartscaled);
            this.gobject.RotateTransform((float)rotation);
            this.gobject.TranslateTransform((float)-xstartscaled, (float)-ystartscaled);


			//draw straight
			this.gobject.DrawPath(pen1, straight);


            //rotate the right branch, draw right branch, Rotate object to original location
            this.gobject.TranslateTransform((float)xstartscaled, (float)(ystartscaled - ((188 / scale) / 2)));
            this.gobject.RotateTransform((float)24.3);
            this.gobject.TranslateTransform((float)-xstartscaled, (float)-(ystartscaled - ((188 / scale) / 2)));

            this.gobject.DrawPath(pen1, branch);

            this.gobject.TranslateTransform((float)xstartscaled, (float)(ystartscaled - ((188 / scale) / 2)));
            this.gobject.RotateTransform((float)-24.3);
            this.gobject.TranslateTransform((float)-xstartscaled, (float)-(ystartscaled - ((188 / scale) / 2)));

            //rotate the left branch, draw left branch, Rotate Object to original Location
            this.gobject.TranslateTransform((float)xstartscaled, (float)(ystartscaled - ((188 / scale) / 2)));
            this.gobject.RotateTransform((float)204.3);
            this.gobject.TranslateTransform((float)-xstartscaled, (float)-(ystartscaled - ((188 / scale) / 2)));

            this.gobject.DrawPath(pen1, branch);

            this.gobject.TranslateTransform((float)xstartscaled, (float)(ystartscaled - ((188 / scale) / 2)));
            this.gobject.RotateTransform((float)-204.3);
            this.gobject.TranslateTransform((float)-xstartscaled, (float)-(ystartscaled - ((188 / scale) / 2)));

            //Rotate object to origial position
            this.gobject.TranslateTransform((float)xstartscaled, (float)ystartscaled);
            this.gobject.RotateTransform((float)-rotation);
            this.gobject.TranslateTransform((float)-xstartscaled, (float)-ystartscaled);
        }
    }
}
